#ifndef __BUOLA_SCENE_CBONE_H__
#define __BUOLA_SCENE_CBONE_H__

#include <buola/scene.h>
#include <buola/scene/cskeleton.h>
#include <buola/scene/cbonetransform.h>

namespace buola { namespace scene {

class CBone : public UShared
{
public:
    struct SJoint
    {
        EJointType mType;
        mat::CVec3d mAxis;
        mat::CVec3d mZero;
        bool mAngles;
        double mA,mB,mC,mD;
        bool mSpheres;
        mat::CMat34d mInner,mOuter;
        double mValue;
    };

    CBone(const std::string &pName,const mat::CVec3d &pOrigin,const mat::CVec3d &pEndPoint,const mat::C3DRotation &pOrientation);
    ~CBone();

    void AddChild(PBone pBone);
    void AddJoint(EJointType pType,const mat::CVec3d &pAxis,const mat::CVec3d &pZero);
    void AddJoint(EJointType pType,const mat::CVec3d &pAxis,const mat::CVec3d &pZero,double pA,double pB,double pC,double pD);
    void AddJoint(EJointType pType,const mat::CVec3d &pAxis,const mat::CVec3d &pZero,double pA,double pB,double pC,double pD,
                  const mat::CMat34d &pInner,const mat::CMat34d &pOuter);
    void SetJointValue(EJointType pType,double pValue);
    double GetJointValue(EJointType pType);

    
    double CalcBlendWeight(const mat::CVec3d &pPos);
    
    void AssignIndex(CSkeleton::SAssignIndexContext &pContext);
    void SkinMesh(CSkeleton::SSkinMeshContext &pContext);
    void FillMatrices(CSkeleton::SFillMatricesContext &pContext);
    void Render(CRenderContext &pContext,CSkeleton *pSkeleton);

    const mat::CVec3d &GetOrigin()        {   return mOrigin;     }
    const mat::CVec3d &GetEndPoint()      {   return mEndPoint;   }
    const mat::CQuat_d &GetOrientation() {   return mOrientation;    }

    const std::vector<PBone> &GetChildren()    {   return mChildren;   }
    CBone *GetParent()  {   return mParent; }

    int GetIndex()  {   return mBoneIndex;  }
    
    const std::string &GetName()    {   return mName;   }

    PBoneTransform GetTransform()   {   return mTransform;  }
    
    mat::CVec3d GetTransformedOrigin();
    mat::CVec3d GetTransformedEndPoint();

private:
    std::vector<PBone> mChildren;
    CBone *mParent;

    std::vector<SJoint*> mJoints;

    int mBoneIndex;
    
    std::string mName;
    mat::CVec3d mOrigin;
    mat::CVec3d mEndPoint;
    mat::CQuat_d mOrientation;

    PBoneTransform mTransform;

    friend class CBoneTransform;
};

/*namespace scene*/ } /*namespace buola*/ }

#endif
